// src/debugAdapter.ts
import { DebugSession, InitializedEvent, StoppedEvent } from '@vscode/debugadapter';
import { DebugProtocol } from '@vscode/debugprotocol';
import * as vscode from 'vscode';
// 正确的导入方式
import { Socket } from 'net';
import * as path from 'path';

interface Breakpoint {
  file: string;
  line: number;
}
// 新增调试适配器工厂类
export class LuaDebugAdapterDescriptorFactory implements vscode.DebugAdapterDescriptorFactory {
  createDebugAdapterDescriptor(_session: vscode.DebugSession): vscode.ProviderResult<vscode.DebugAdapterDescriptor> {
    return new vscode.DebugAdapterInlineImplementation(new LuaDebugSession());
  }
}
export class LuaDebugSession extends DebugSession {
  private static THREAD_ID = 1;
  private socket: Socket;
  private breakpoints = new Map<string, Breakpoint[]>();
  // 添加调用栈和变量存储
  private callStack: Array<{frames: DebugProtocol.StackFrame[], vars: any}> = [];
  private variableId = 1;

  constructor() {
    super();
    this.socket = new Socket();
    this.socket.connect(12346, '127.0.0.1');

    this.socket.on('data', (data) => {
      const msg = data.toString();
      if (msg.startsWith('BREAK')) {
        const [_, file, line] = msg.split('|');
        this.sendEvent(new StoppedEvent('breakpoint', LuaDebugSession.THREAD_ID));
      }    // 新增C++调用Lua的协议处理
      else if (msg.startsWith('CALL_LUA')) {
        const [_, luaFile, luaLine, cppFrame, varData] = msg.split('|');
        this.handleCrossLanguageCall(luaFile, parseInt(luaLine), cppFrame, JSON.parse(varData));
      }
    });
  }

  // 新增跨语言调用处理方法
  private handleCrossLanguageCall(luaFile: string, luaLine: number, cppFrame: string, variables: any) {
    const stackId = this.callStack.length + 1;
    
    // 创建混合调用堆栈
    const frames = [
      {
        id: stackId,
        name: `Lua: ${path.basename(luaFile)}:${luaLine}`,
        source: { path: luaFile },
        line: luaLine,
        column: 0
      },
      {
        id: stackId + 1,
        name: `C++: ${cppFrame}`,
        source: { path: cppFrame.split(':')[0] },
        line: parseInt(cppFrame.split(':')[1]),
        column: 0
      }
    ];
    // 存储变量信息
    this.callStack.push({
      frames,
      vars: this.parseVariables(variables)
    });
    // 检查是否需要触发断点
    if (this.checkBreakpoint(luaFile, luaLine)) {
      this.sendEvent(new StoppedEvent('breakpoint', LuaDebugSession.THREAD_ID));
    }
  }

  // 变量解析方法
  private parseVariables(data: any): DebugProtocol.Variable[] {
    return Object.entries(data).map(([name, value]) => ({
      name,
      value: JSON.stringify(value),
      variablesReference: 0,
      type: typeof value
    }));
  }

  protected attachRequest(response: DebugProtocol.AttachResponse, args: DebugProtocol.AttachRequestArguments, request?: DebugProtocol.Request): void {
    // 添加文件类型验证
    // 为 AttachRequestArguments 添加 program 属性
    interface AttachRequestArgumentsWithProgram extends DebugProtocol.AttachRequestArguments {
      program?: string;
    }
    const argsWithProgram = args as AttachRequestArgumentsWithProgram;
    if (!argsWithProgram.program?.endsWith('.lua')) {
      this.sendErrorResponse(response, 1001, "Only Lua files can be debugged");
      return;
    }
    // 添加实际连接逻辑
    this.socket.connect(12346, '127.0.0.1', () => {
      this.sendResponse(response);
    });
  }
  
  protected initializeRequest(response: DebugProtocol.InitializeResponse, args: DebugProtocol.InitializeRequestArguments): void {
    response.body = {
      supportsConfigurationDoneRequest: true,
      supportsSetVariable: true,
      supportsStepBack: false,
      supportsConditionalBreakpoints: true
    };

    if (!args?.adapterID?.startsWith('lua-cpp')) {
      this.sendErrorResponse(response, 1002, "Invalid debug configuration");
      return;
    }

    this.sendResponse(response);
    this.sendEvent(new InitializedEvent());
  }

  protected setBreakPointsRequest(
    response: DebugProtocol.SetBreakpointsResponse,
    args: DebugProtocol.SetBreakpointsArguments
  ): void {
    const path = args.source.path!;
    // 新增文件类型验证过滤 非lua断点文件
    if (!path.endsWith('.lua')) {
      response.body = {
        breakpoints: []
      };
      this.sendResponse(response);
      return;
    }
    const bps = args.breakpoints?.map(bp => ({
      file: path,
      line: bp.line
    })) || [];
    this.breakpoints.set(path, bps);
    this.socket.write(`SET_BP|${path}|${bps.map(b => b.line).join(',')}`);

    response.body = {
      breakpoints: bps.map(bp => ({ verified: true, line: bp.line }))
    };
    this.sendResponse(response);
  }

  protected threadsRequest(response: DebugProtocol.ThreadsResponse): void {
    response.body = {
      threads: [{ id: LuaDebugSession.THREAD_ID, name: "Lua Main Thread" }]
    };
    this.sendResponse(response);
  }

  protected stackTraceRequest(response: DebugProtocol.StackTraceResponse): void {
    this.socket.write('GET_STACK', (err) => {
      // 示例堆栈数据
      response.body = {
        stackFrames: [{
          id: 1,
          name: 'main()',
          line: 10,
          column: 0,
          source: { path: 'test.lua' }
        }]
      };
      this.sendResponse(response);
    });
  }

  protected continueRequest(response: DebugProtocol.ContinueResponse): void {
    this.socket.write('CONTINUE');
    this.sendResponse(response);
  }

  protected nextRequest(response: DebugProtocol.NextResponse): void {
    this.socket.write('STEP_OVER');
    this.sendResponse(response);
  }

// 添加断点条件验证
  private checkBreakpoint(file: string, line: number): boolean {
    return this.breakpoints.get(file)?.some(bp => bp.line === line) || false;
  }

  // 新增变量请求处理
  protected variablesRequest(response: DebugProtocol.VariablesResponse, args: DebugProtocol.VariablesArguments): void {
    const frameId = (args as any).frameId; // 使用类型断言解决类型问题
    const vars = this.callStack[frameId]?.vars || [];
    response.body = { variables: vars };
    this.sendResponse(response);
  }

}